// C++11语言特性
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <typeinfo>
#include <initializer_list>
#include <functional>  // 包装器 + 绑定
using namespace std;

// void test1()
// {
//     // 列表初始化
//     int arr[] = {1, 2, 3, 4};
//     for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); ++i)
//     {
//         cout << arr[i] << " ";
//     }
//     cout << endl;

//     // vector<int> v = {1, 2, 3};
//     // for (int i = 0; i < v.size(); ++i)
//     // {
//     //     cout << v[i] << " ";
//     // }
//     // cout << endl;

//     int x = {1};
//     int y {2};
//     int ar1[]{1, 2, 3};
//     int ar2[3]{1};
//     int* ar3 = new int[3]{2, 4, 5};

//     vector<int> v = {1, 2, 3};
//     unordered_map<string, string> m = {{"language", "语言"}, {"practical", "实用"}};
//     for (auto e : v) cout << e << " ";
//     cout << "\n" << m["language"] << m["practical"] << endl; 

//     m = {{"玉子", "饼藏"}};
//     cout << m["玉子"] << endl;

//     auto e  = {1, 2};
//     cout << typeid(e).name() << endl;
// }


// class Student
// {
// public:
//     Student(string name, size_t id)
//     :_name(name), _id(id)
//     {}
//     const string& PutName()
//     {
//         return _name;
//     }
//     size_t PutId()
//     {
//         return _id;
//     }
// private:
//     string _name;
//     size_t _id;
// };

// class StudentManagement
// {
// public:
//     // 实现列表初始化
//     StudentManagement(const initializer_list<Student>& l)
//     :_size(l.size())
//     {
//         for (auto& e : l)  // 底层有迭代器 - 可以使用范围for
//         {
//             _v.push_back(e);
//         }
//     }

//     void Printlist()  // 打印测试
//     {
//         for (auto& e : _v)
//         {
//             cout << e.PutName() << ":" << e.PutId() << endl;
//         }
//     }
// private:
//     vector<Student> _v;
//     size_t _size;
// };

// void test2()
// {
//     // 测试自定义类型列表初始化
//     Student s = {"张三", 1};  // 默认类型转换
//     cout << s.PutName() << ":" << s.PutId() << endl << endl;
//     StudentManagement ss{{"李四", 2}, {"王五", 3}, {"小明", 4}, {"小美", 5}};  // 列表初始化对自定义类型进行多个对象初始化：默认类型转换 + 列表初始化构造函数
//     ss.Printlist();
// }

// void test3()
// {
//     // 类型推导 范围for
//     unordered_map<string, string> m{{"我不高兴", "不愉快です"}, {"我很好奇!", "わたし、気になります！"}};
//     // unordered_map<string, string>::iterator ib = m.begin();
//     auto ib = m.begin();
//     while (ib != m.end())
//     {
//         cout << ib->first << ":" << ib->second << endl;
//         ++ib;
//     }

//     // auto e;
//     cout << typeid(ib).name() << endl << endl;  // 之前迭代器的对象

//     int x = 2;
//     decltype(x) y;  // 定义对象
//     y = x;
//     cout << y << endl;
//     double z = 2.1;
//     cout << typeid(decltype(x * y)).name() << endl;  // int int
//     cout << typeid(decltype(x * z)).name() << endl;  // int double

//     vector<int> vv = {1, 2, 3, 4, 5, 6};
//     for (auto& e : vv)
//     {
//         cout << e << " ";
//         e++;  // 加上引用修改里面的值
//     }
//     cout << endl;  
//     for (auto e : vv)
//     {
//         cout << e << " ";  // 正常范围for遍历，并且验证上面是否修改
//     }
//     cout << endl;
// }

// class A
// {

// };

// class B : public A
// {};

// class C final
// {};

// class D : public C
// {};

// class A
// {
// public:
//     virtual void test() final  // 表示此虚函数不可被重写
//     {}
// };

// class B : public A
// {
// public:
//     void test()
//     {};
// };

// class A
// {
// public:
//     virtual void test1()
//     {}

//     void test2()
//     {}
// };

// class B : public A
// {
// public:
//     void test1() override  // 基类必须存在对应的虚函数
//     {}

//     void test2() override
//     {}
// };

// class A
// {
// public:
//     A(int n)
//     {};

//     A() = default;  // 表示让默认构造函数生成 - 本来是不会生成的
// };
// void test4()
// {
//     A a;
//     A b(2);
// }

// class A
// {
// public:
//     A(int n)
//     {};

//     A(const A&) = delete;  // 默认拷贝构造给删除了
// };

// void test4()
// {
//     A a(2);
//     // A b(a);
// }
// int add(int x, int y)
// {
//     return x + y;  // 传值返回
// }

// class Student
// {
// public:
//     Student(string name, size_t id)
//     :_name(name), _id(id)
//     {}
//     Student() = default;  // 生成默认构造函数
//     // 拷贝构造
//     Student(const Student& stu)
//     {
//         _name = stu._name;  // 调用string类的赋值重载
//         _id = stu._id;
//         cout << "Student发生了拷贝构造" << endl;
//     }
//     // 赋值重载
//     Student& operator=(const Student& stu)
//     {
//         _name = stu._name;
//         _id = stu._id;
//         cout << "Student发生了赋值重载" << endl;
//         return *this;
//     }
//     // 移动构造
//     Student(Student&& stu)  // 右值识别进入函数
//     {
//         stu._name.swap(_name);  // 转移资源
//         _id = stu._id;
//         cout << "Student发生了移动构造" << endl;
//     }
//     // 移动赋值
//     Student& operator=(Student&& stu)
//     {
//         stu._name.swap(_name);  // 转移资源
//         _id = stu._id;
//         cout << "Student发生了移动赋值" << endl;
//         return *this;
//     }
//     const string& PutName()
//     {
//         return _name;
//     }
//     size_t PutId()
//     {
//         return _id;
//     }

// private:
//     string _name;
//     size_t _id;
// };

// class StudentManagement
// {
// public:
//     // 实现列表初始化
//     StudentManagement(const initializer_list<Student>& l)
//     :_size(l.size())
//     {
//         for (auto& e : l)  // 底层有迭代器 - 可以使用范围for
//         {
//             _v.push_back(e);
//         }
//     }
//     void Printlist()  // 打印测试
//     {
//         for (auto& e : _v)
//         {
//             cout << e.PutName() << ":" << e.PutId() << endl;
//         }
//     }

//     // 假设上述程序实现id去重操作
//     Student IdOfStudent(size_t id)  // 根据id返回一个新学生对象(不是vector内的)，不存在就设置一个空对象
//     {
//         for(auto& e : _v)
//         {
//             if (e.PutId() == id) return e;  // 传值返回
//         }
//         return Student ("null", id);  // 不存在返回空的新对象
//     }
    
// private:
//     vector<Student> _v;
//     size_t _size;
// };

// class A
// {
// public:
//     A(size_t n)
//     :_capacity(n)
//     {
//         arr = new int[n];
//     }

//     int* arr = nullptr;  // 缺省参数
//     size_t _capacity = 0;
// };
// void test5()
// {
    // 引用

    // // 左值
    // int a = 10;
    // int& _a = a;
    // cout << &a << endl;
    // const int b = 12;
    // cout <<  &b << endl;
    // a = b;  // 可以出现等号的左边
    // // 右值
    // int&& d = 10;  // 常量 - 纯右值
    // int&& e = a + b;  // 表达式相加返回的是一个临时对象
    // int&& f = add(1, 2);  // 将亡值或者也是一个临时对象
    // int& g = f;  // f此时也是一个左值

    // const int& a = 10;  // const修饰后的左值引用可以引用右值
    // const int& b = add(1, 2);  // 同上

    // int a = 10;
    // int&& c = move(a);
    // cout << c << endl;
    // cout << a << endl;

    // StudentManagement sm = {{"张三", 1}, {"李四", 2}, {"王五", 3}};
    // cout << endl << endl;
    // Student s1 = sm.IdOfStudent(2);  // 拷贝构造+移动构造：vector中的对象-临时对象-外面的对象
    // cout << endl;
    // Student s2 = sm.IdOfStudent(4);  // 2次移动构造：匿名对象-临时对象-外面的对象
    // cout << endl;
    // Student s4;
    // s4 = Student("xxx", 0);  // 赋值 - 移动赋值
// }

// // 重载不同类型参数的相同函数名
// void Func(int& x)
// {
//     cout << "左值" << endl;
// }

// void Func(int&& x)
// {
//     cout << "右值" << endl;
// }

// void Func(const int& x)
// {
//     cout << "const左值" << endl;
// }

// void Func(const int&& x)
// {
//     cout << "const右值" << endl;
// }

// template<class T>
// void test(T&& t)  // 万能引用
// {
//     Func(forward<T>(t));  // 完美转发
// }
// void test6()
// {// 完美转发
//     test(1);  // right

//     int x = 1;
//     test(x);  // left
//     test(move(x));  // right

//     const int y = 2;
//     test(y);  // const left
//     test(move(y));  // const right
// }

// void test()
// {
//     cout << endl;
// }

// template<class T, class ...Args>
// void test(const T& val, Args... args)
// {
//     cout << val << ":" << sizeof...(args) << endl;
//     test(args...);
// }

// template<class T>
// int PrintArgs(const T& val)
// {
//     cout << val << endl;
//     return 0;
// }

// template<class ...Args>
// void test(Args... args)
// {
//     int arr[] = {PrintArgs(args)...};
//     cout << endl;
// }

// void test7()
// {
//     test(1, 'a', 'b', "ds", 343);
//     test('A', 2, 'c');
// }

// void test8()
// {
//     // lambda表达式
//     // 捕捉列表
//     int x = 10, y = 2;
//     auto func1 = [x, y](){ return x + y; };
//     cout << func1() << endl;
//     cout << endl;
//     // 默认const 使用关键字mutable，去掉const
//     auto func2 = [x, y]()mutable{ y -= 6; return x + y; };
//     cout << func2() << endl;
//     cout << y << endl;  // 只是传值返回
//     cout << endl;
//     // 引用捕捉
//     auto func3 = [&x, &y](){ int tmp = x; x = y; y = tmp; };
//     cout << "x=" << x << " y=" << y << endl;
//     func3();
//     cout << "x=" << x << " y=" << y << endl;
//     cout << endl;
//     // 混合使用
//     int z = 8;
//     auto func4 = [&x, &y, z](){
//         x = 10;
//         y = 2;
//         cout << z << endl;
//     };
//     func4();
//     cout << "x=" << x << " y=" << y << endl;
//     auto func5 = [=, &x](){  // 符号=先 x引用捕捉，其余传值捕捉
//         x = 2;
//         cout << y << " " << z << endl;
//     };
//     func5();
//     cout << "x=" << x << endl;
//     auto func6 = [&, x](){ // 符号在前 x传值捕捉，其余引用捕捉
//         cout << x << endl;
//         y = z = 0;
//     };
//     cout << "y=" << y << " z=" << z << endl;
//     cout << endl;

//     // 参数列表
//     auto func7 = [](int& x, int& y){
//         int tmp = x;
//         x = y;
//         y = tmp;
//     };
//     x = 4;
//     cout << "x=" << x << " y=" << y << endl;
//     func7(x, y);
//     cout << "x=" << x << " y=" << y << endl;
//     cout << endl;
// }

void func1()
{
    cout << "わたし、気になります！" << endl;  // 我很好奇
}

struct func2
{
    void operator()()
    {
        cout << "不愉快です" << endl;  // 我不高兴
    }
};

class test
{
public:
    int fun4(int a, int b)
    {
        return a + b;
    }

    static int fun5(int a, int b)
    {
        return a - b;   
    }
};

void test9()
{
    // 包装器的使用 + 绑定
    // function<void()> Func1 = func1;  // 函数指针
    // function<void()> Func2 = func2();  // 仿函数对象 - 此处为匿名对象
    // function<void(string, string)> Func3 = [](const string& x = "玉子", const string& y = "市场"){  // 注意虽然给了缺省参数，但是包装器上层包装必须要传参的哦~
    //     cout << x + y << endl;
    // };  // lambda表达式
    // function<int(test, int, int)> Func4 = &test::fun4;  // 成员函数
    // function<int(int, int)> Func5 = &test::fun5;  // 静态成员函数，不存在this指针。
    // Func1();
    // Func2();
    // Func3("玉子", "市场");
    // cout << Func4(test(), 1, 1) << endl;  // 别忘了传入对象
    // cout << Func5(2, 2) << endl;
    
    // 首先简单传一个函数对象
    auto t1 = bind(func1);  // 此时返回的也是一个函数对象
    t1();
    cout << typeid(t1).name() << endl;
    auto t2 = bind([](int i){cout << i << " 个" << endl;}, placeholders::_1);  // 此时lambda匿名对象有参数，那么就要用到placeholders中的占位了。
    t2(2);
    // 我们想统一test::func4 和 func5 的function怎么办 - 原本是：<int(int, int)> <int(test, int, int)>
    function<int(int, int)> Func6 = bind(&test::fun4, test(), placeholders::_1, placeholders::_2);  // 在bind中首先传参，这样就能保证function一致了
    function<int(int, int)> Func7 = bind(&test::fun5, placeholders::_1, placeholders::_2);
    // 类型统一很有意义，可以看下面的一段代码
    unordered_map<char, function<int(int, int)>> m;
    m['+'] = Func6;
    m['-'] = Func7;
    char flag;
    int a, b;
    while(cin >> flag)
    {
        cin >> a >> b;
        cout << m[flag](a, b) << endl;
    }
}

int main()
{
    test9();
    return 0;
}